Added new symbols
authorAlexander Larsson <alexl@redhat.com>
Thu, 4 May 2006 13:43:32 +0000 (13:43 +0000)
committerAlexander Larsson <alexl@src.gnome.org>
Thu, 4 May 2006 13:43:32 +0000 (13:43 +0000)
2006-05-04  Alexander Larsson  <alexl@redhat.com>

* gtk/gtk.symbols:
Added new symbols

* gtk/gtkpagesetupunixdialog.c:
* gtk/gtkprintunixdialog.c:
Destroy backends when finalizing dialogs.
Fix printer leak in selected_printer_changed.

* gtk/gtkprintbackend.[ch]:
Convert from interface to baseclass.
Move printer hashtable here so that the baseclass can handle
the slightly complicated ownership model.
Add gtk_print_backend_destroy which runs the dispose method,
causing the ref-cycles between the backend and its printers
to be broken.
Add gtk_print_backend_unref_at_idle().

* gtk/gtkprinter.[ch]:
GtkPrinter objects now ref their backend so that its always
availible, since its needed for the printer object to work.
This causes a reference-cycle that is broken using
gtk_print_backend_destroy.
Add gtk_printer_compare.

* gtk/gtkprintoperation-private.h:
* gtk/gtkprintoperation-unix.c:
* gtk/gtkprintoperation.c:
Implement !show_dialog for unix.
Make sure the print data is fully spooled before returning
from a sync run_dialog.

* modules/printbackends/cups/gtkcupsutils.[ch]:
Add gtk_cups_request_ipp_add_strings

* modules/printbackends/cups/gtkprintbackendcups.c:
* modules/printbackends/cups/gtkprintercups.c:
* modules/printbackends/lpr/gtkprintbackendlpr.c:
* modules/printbackends/pdf/gtkprintbackendpdf.c:
Convert backends to derive instead of implementing interface.
Move common code into baseclass.
CUPS:
  Remove the printer polling in dispose, not finalize.
  In the cups watch, remove the backend at idle instead of
  immediately, since the unref can cause the module to be unloaded.
  Limit the number of printer attributes requested
  Get printer uri in initial printer listing so that we can use
  the printer object immediately.

* tests/Makefile.am:
* tests/testnouiprint.c:
Add testcase for !show_dialog.

20 files changed:
ChangeLog
ChangeLog.pre-2-10
gtk/gtk.symbols
gtk/gtkpagesetupunixdialog.c
gtk/gtkprintbackend.c
gtk/gtkprintbackend.h
gtk/gtkprinter.c
gtk/gtkprinter.h
gtk/gtkprintoperation-private.h
gtk/gtkprintoperation-unix.c
gtk/gtkprintoperation.c
gtk/gtkprintunixdialog.c
modules/printbackends/cups/gtkcupsutils.c
modules/printbackends/cups/gtkcupsutils.h
modules/printbackends/cups/gtkprintbackendcups.c
modules/printbackends/cups/gtkprintercups.c
modules/printbackends/lpr/gtkprintbackendlpr.c
modules/printbackends/pdf/gtkprintbackendpdf.c
tests/Makefile.am
tests/testnouiprint.c [new file with mode: 0644]

index ef7b5f310e15f1ee5c0aa950cafe621b588f4b94..d3df94cc3c05039fd0807deb34864c471980d2d7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+2006-05-04  Alexander Larsson  <alexl@redhat.com>
+
+       * gtk/gtk.symbols:
+       Added new symbols
+       
+       * gtk/gtkpagesetupunixdialog.c:
+       * gtk/gtkprintunixdialog.c:
+       Destroy backends when finalizing dialogs.
+       Fix printer leak in selected_printer_changed.
+       
+       * gtk/gtkprintbackend.[ch]:
+       Convert from interface to baseclass.
+       Move printer hashtable here so that the baseclass can handle
+       the slightly complicated ownership model.
+       Add gtk_print_backend_destroy which runs the dispose method,
+       causing the ref-cycles between the backend and its printers
+       to be broken.
+       Add gtk_print_backend_unref_at_idle().
+       
+       * gtk/gtkprinter.[ch]:
+       GtkPrinter objects now ref their backend so that its always
+       availible, since its needed for the printer object to work.
+       This causes a reference-cycle that is broken using
+       gtk_print_backend_destroy.
+       Add gtk_printer_compare.
+       
+       * gtk/gtkprintoperation-private.h:
+       * gtk/gtkprintoperation-unix.c:
+       * gtk/gtkprintoperation.c:
+       Implement !show_dialog for unix.
+       Make sure the print data is fully spooled before returning
+       from a sync run_dialog.
+       
+       
+       * modules/printbackends/cups/gtkcupsutils.[ch]:
+       Add gtk_cups_request_ipp_add_strings
+       
+       * modules/printbackends/cups/gtkprintbackendcups.c:
+       * modules/printbackends/cups/gtkprintercups.c:
+       * modules/printbackends/lpr/gtkprintbackendlpr.c:
+       * modules/printbackends/pdf/gtkprintbackendpdf.c:
+       Convert backends to derive instead of implementing interface.
+       Move common code into baseclass.
+       CUPS:
+         Remove the printer polling in dispose, not finalize.
+         In the cups watch, remove the backend at idle instead of
+         immediately, since the unref can cause the module to be unloaded.
+         Limit the number of printer attributes requested
+         Get printer uri in initial printer listing so that we can use
+         the printer object immediately.
+       
+       * tests/Makefile.am:
+       * tests/testnouiprint.c:
+       Add testcase for !show_dialog.
+
 2006-05-04  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtk.symbols:
index ef7b5f310e15f1ee5c0aa950cafe621b588f4b94..d3df94cc3c05039fd0807deb34864c471980d2d7 100644 (file)
@@ -1,3 +1,58 @@
+2006-05-04  Alexander Larsson  <alexl@redhat.com>
+
+       * gtk/gtk.symbols:
+       Added new symbols
+       
+       * gtk/gtkpagesetupunixdialog.c:
+       * gtk/gtkprintunixdialog.c:
+       Destroy backends when finalizing dialogs.
+       Fix printer leak in selected_printer_changed.
+       
+       * gtk/gtkprintbackend.[ch]:
+       Convert from interface to baseclass.
+       Move printer hashtable here so that the baseclass can handle
+       the slightly complicated ownership model.
+       Add gtk_print_backend_destroy which runs the dispose method,
+       causing the ref-cycles between the backend and its printers
+       to be broken.
+       Add gtk_print_backend_unref_at_idle().
+       
+       * gtk/gtkprinter.[ch]:
+       GtkPrinter objects now ref their backend so that its always
+       availible, since its needed for the printer object to work.
+       This causes a reference-cycle that is broken using
+       gtk_print_backend_destroy.
+       Add gtk_printer_compare.
+       
+       * gtk/gtkprintoperation-private.h:
+       * gtk/gtkprintoperation-unix.c:
+       * gtk/gtkprintoperation.c:
+       Implement !show_dialog for unix.
+       Make sure the print data is fully spooled before returning
+       from a sync run_dialog.
+       
+       
+       * modules/printbackends/cups/gtkcupsutils.[ch]:
+       Add gtk_cups_request_ipp_add_strings
+       
+       * modules/printbackends/cups/gtkprintbackendcups.c:
+       * modules/printbackends/cups/gtkprintercups.c:
+       * modules/printbackends/lpr/gtkprintbackendlpr.c:
+       * modules/printbackends/pdf/gtkprintbackendpdf.c:
+       Convert backends to derive instead of implementing interface.
+       Move common code into baseclass.
+       CUPS:
+         Remove the printer polling in dispose, not finalize.
+         In the cups watch, remove the backend at idle instead of
+         immediately, since the unref can cause the module to be unloaded.
+         Limit the number of printer attributes requested
+         Get printer uri in initial printer listing so that we can use
+         the printer object immediately.
+       
+       * tests/Makefile.am:
+       * tests/testnouiprint.c:
+       Add testcase for !show_dialog.
+
 2006-05-04  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtk.symbols:
index eb09e7da2435ad001064abb910547283710e7088..afcbe2c123d7ab06f5972df5151833c8e14fe984 100644 (file)
@@ -2550,9 +2550,11 @@ gtk_paper_size_get_default
 gtk_print_backend_error_quark
 gtk_print_backend_get_type G_GNUC_CONST
 gtk_print_backend_get_printer_list  
+gtk_print_backend_printer_list_is_done
 gtk_print_backend_find_printer
 gtk_print_backend_print_stream
 gtk_print_backend_load_modules
+gtk_print_backend_unref_at_idle
 #endif
 #endif
 #endif
index 72a5cd074c08a1cdbbc46d9e5ab57b951d905b43..5daf8549595cfe1420459803e335944ea19307d3 100644 (file)
@@ -110,6 +110,17 @@ static void populate_dialog                      (GtkPageSetupUnixDialog *dialog
 static void fill_paper_sizes_from_printer        (GtkPageSetupUnixDialog *dialog,
                                                  GtkPrinter             *printer);
 static void run_custom_paper_dialog              (GtkPageSetupUnixDialog *dialog);
+static void printer_added_cb                     (GtkPrintBackend        *backend,
+                                                 GtkPrinter             *printer,
+                                                 GtkPageSetupUnixDialog *dialog);
+static void printer_removed_cb                   (GtkPrintBackend        *backend,
+                                                 GtkPrinter             *printer,
+                                                 GtkPageSetupUnixDialog *dialog);
+static void printer_status_cb                    (GtkPrintBackend        *backend,
+                                                 GtkPrinter             *printer,
+                                                 GtkPageSetupUnixDialog *dialog);
+
+
 
 static const char * const common_paper_sizes[] = {
   "na_letter",
@@ -369,7 +380,9 @@ gtk_page_setup_unix_dialog_finalize (GObject *object)
 {
   GtkPageSetupUnixDialog *dialog = GTK_PAGE_SETUP_UNIX_DIALOG (object);
   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
+  GtkPrintBackend *backend;
+  GList *node;
+  
   if (priv->request_details_tag)
     {
       g_source_remove (priv->request_details_tag);
@@ -397,6 +410,21 @@ gtk_page_setup_unix_dialog_finalize (GObject *object)
   g_free (priv->waiting_for_printer);
   priv->waiting_for_printer = NULL;
 
+  for (node = priv->print_backends; node != NULL; node = node->next)
+    {
+      backend = GTK_PRINT_BACKEND (node->data);
+
+      g_signal_handlers_disconnect_by_func (backend, printer_added_cb, dialog);
+      g_signal_handlers_disconnect_by_func (backend, printer_removed_cb, dialog);
+      g_signal_handlers_disconnect_by_func (backend, printer_status_cb, dialog);
+
+      gtk_print_backend_destroy (backend);
+      g_object_unref (backend);
+    }
+  
+  g_list_free (priv->print_backends);
+  priv->print_backends = NULL;
+
   G_OBJECT_CLASS (gtk_page_setup_unix_dialog_parent_class)->finalize (object);
 }
 
index 32e6596d0a6b3dca6c37af3164006f117156b452..272d2f395785f38c89a8429797552694a6f720ee 100644 (file)
 #include "gtkprintbackend.h"
 #include "gtkalias.h"
 
-static void gtk_print_backend_base_init (gpointer g_class);
+#define GTK_PRINT_BACKEND_GET_PRIVATE(o)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendPrivate))
+
+static void gtk_print_backend_dispose (GObject *object);
+
+struct _GtkPrintBackendPrivate
+{
+  GHashTable *printers;
+  guint printer_list_requested : 1;
+  guint printer_list_done : 1;
+};
+
+enum {
+  PRINTER_LIST_CHANGED,
+  PRINTER_LIST_DONE,
+  PRINTER_ADDED,
+  PRINTER_REMOVED,
+  PRINTER_STATUS_CHANGED,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static GObjectClass *backend_parent_class;
 
 GQuark
 gtk_print_backend_error_quark (void)
@@ -142,7 +165,7 @@ _gtk_print_backend_module_class_init (GtkPrintBackendModuleClass *class)
 {
   GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
-  
+
   module_class->load = gtk_print_backend_module_load;
   module_class->unload = gtk_print_backend_module_unload;
 
@@ -272,107 +295,255 @@ gtk_print_backend_load_modules ()
 /*****************************************
  *             GtkPrintBackend           *
  *****************************************/
-GType
-gtk_print_backend_get_type (void)
+
+G_DEFINE_TYPE (GtkPrintBackend, gtk_print_backend, G_TYPE_OBJECT);
+
+static void
+gtk_print_backend_class_init (GtkPrintBackendClass *class)
 {
-  static GType print_backend_type = 0;
+  GObjectClass *object_class;
+  object_class = (GObjectClass *) class;
 
-  if (!print_backend_type)
+  backend_parent_class = g_type_class_peek_parent (class);
+  
+  object_class->dispose = gtk_print_backend_dispose;
+
+  g_type_class_add_private (class, sizeof (GtkPrintBackendPrivate));
+
+  
+  signals[PRINTER_LIST_CHANGED] =
+    g_signal_new ("printer-list-changed",
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_changed),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+  signals[PRINTER_LIST_DONE] =
+      g_signal_new ("printer-list-done",
+                   G_TYPE_FROM_CLASS (class),
+                   G_SIGNAL_RUN_LAST,
+                   G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_done),
+                   NULL, NULL,
+                   g_cclosure_marshal_VOID__VOID,
+                   G_TYPE_NONE, 0);
+  signals[PRINTER_ADDED] =
+    g_signal_new ("printer-added",
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_added),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__OBJECT,
+                 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
+  signals[PRINTER_REMOVED] =
+    g_signal_new ("printer-removed",
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_removed),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__OBJECT,
+                 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
+  signals[PRINTER_STATUS_CHANGED] =
+    g_signal_new ("printer-status-changed",
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_status_changed),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__OBJECT,
+                 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
+}
+
+static void
+gtk_print_backend_init (GtkPrintBackend *backend)
+{
+  GtkPrintBackendPrivate *priv;
+
+  priv = backend->priv = GTK_PRINT_BACKEND_GET_PRIVATE (backend); 
+
+  priv->printers = g_hash_table_new_full (g_str_hash, g_str_equal, 
+                                         (GDestroyNotify) g_free,
+                                         (GDestroyNotify) g_object_unref);
+}
+
+static void
+gtk_print_backend_dispose (GObject *object)
+{
+  GtkPrintBackend *backend;
+  GtkPrintBackendPrivate *priv;
+
+  backend = GTK_PRINT_BACKEND (object);
+  priv = backend->priv;
+
+  /* We unref the printers in dispose, not in finalize so that
+     we can break refcount cycles with gtk_print_backend_destroy */
+  if (priv->printers)
     {
-      static const GTypeInfo print_backend_info =
-      {
-       sizeof (GtkPrintBackendIface),  /* class_size */
-       gtk_print_backend_base_init,    /* base_init */
-       NULL,                         /* base_finalize */
-      };
-
-      print_backend_type = g_type_register_static (G_TYPE_INTERFACE,
-                                                "GtkPrintBackend",
-                                                &print_backend_info, 0);
-
-      g_type_interface_add_prerequisite (print_backend_type, G_TYPE_OBJECT);
+      g_hash_table_destroy (priv->printers);
+      priv->printers = NULL;
     }
 
-  return print_backend_type;
+  backend_parent_class->dispose (object);
 }
 
+
 static void
-gtk_print_backend_base_init (gpointer g_class)
+printer_hash_to_sorted_active_list (const gchar *key,
+                                    gpointer value,
+                                    GList **out_list)
 {
-  static gboolean initialized = FALSE;
+  GtkPrinter *printer;
+
+  printer = GTK_PRINTER (value);
+
+  if (gtk_printer_get_name (printer) == NULL)
+    return;
+
+  if (!gtk_printer_is_active (printer))
+    return;
+
+  *out_list = g_list_insert_sorted (*out_list, value, (GCompareFunc) gtk_printer_compare);
+}
+
+
+void
+gtk_print_backend_add_printer (GtkPrintBackend *backend,
+                              GtkPrinter *printer)
+{
+  GtkPrintBackendPrivate *priv;
   
-  if (!initialized)
-    {
-      GType iface_type = G_TYPE_FROM_INTERFACE (g_class);
+  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
 
-      g_signal_new ("printer-list-changed",
-                   iface_type,
-                   G_SIGNAL_RUN_LAST,
-                   G_STRUCT_OFFSET (GtkPrintBackendIface, printer_list_changed),
-                   NULL, NULL,
-                   g_cclosure_marshal_VOID__VOID,
-                   G_TYPE_NONE, 0);
-      g_signal_new ("printer-added",
-                   iface_type,
-                   G_SIGNAL_RUN_LAST,
-                   G_STRUCT_OFFSET (GtkPrintBackendIface, printer_added),
-                   NULL, NULL,
-                   g_cclosure_marshal_VOID__OBJECT,
-                   G_TYPE_NONE, 1, G_TYPE_OBJECT);
-      g_signal_new ("printer-removed",
-                   iface_type,
-                   G_SIGNAL_RUN_LAST,
-                   G_STRUCT_OFFSET (GtkPrintBackendIface, printer_removed),
-                   NULL, NULL,
-                   g_cclosure_marshal_VOID__OBJECT,
-                   G_TYPE_NONE, 1, G_TYPE_OBJECT);
-      g_signal_new ("printer-status-changed",
-                   iface_type,
-                   G_SIGNAL_RUN_LAST,
-                   G_STRUCT_OFFSET (GtkPrintBackendIface, printer_status_changed),
-                   NULL, NULL,
-                   g_cclosure_marshal_VOID__OBJECT,
-                   G_TYPE_NONE, 1, G_TYPE_OBJECT);
+  priv = backend->priv;
 
-      initialized = TRUE;
+  if (!priv->printers)
+    return;
+  
+  g_hash_table_insert (priv->printers,
+                      g_strdup (gtk_printer_get_name (printer)), 
+                      g_object_ref (printer));
+}
+
+void
+gtk_print_backend_remove_printer (GtkPrintBackend *backend,
+                                 GtkPrinter *printer)
+{
+  GtkPrintBackendPrivate *priv;
+  
+  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
+  priv = backend->priv;
+
+  if (!priv->printers)
+    return;
+  
+  g_hash_table_remove (priv->printers,
+                      gtk_printer_get_name (printer));
+}
+
+void
+gtk_print_backend_set_list_done (GtkPrintBackend *backend)
+{
+  if (!backend->priv->printer_list_done)
+    {
+      backend->priv->printer_list_done = TRUE;
+      g_signal_emit (backend, signals[PRINTER_LIST_DONE], 0);
     }
 }
 
+
 GList *
-gtk_print_backend_get_printer_list (GtkPrintBackend *print_backend)
+gtk_print_backend_get_printer_list (GtkPrintBackend *backend)
 {
-  g_return_val_if_fail (GTK_IS_PRINT_BACKEND (print_backend), NULL);
+  GtkPrintBackendPrivate *priv;
+  GList *result;
+  
+  g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
+
+  priv = backend->priv;
+
+  result = NULL;
+  if (priv->printers != NULL)
+    g_hash_table_foreach (priv->printers,
+                          (GHFunc) printer_hash_to_sorted_active_list,
+                          &result);
+
+  if (!priv->printer_list_requested && priv->printers != NULL)
+    {
+      if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
+       GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
+      priv->printer_list_requested = TRUE;
+    }
+  
+  return result;;
+}
 
-  return GTK_PRINT_BACKEND_GET_IFACE (print_backend)->get_printer_list (print_backend);
+gboolean
+gtk_print_backend_printer_list_is_done (GtkPrintBackend *print_backend)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_BACKEND (print_backend), TRUE);
 
+  return print_backend->priv->printer_list_done;
 }
 
 GtkPrinter *
-gtk_print_backend_find_printer (GtkPrintBackend *print_backend,
+gtk_print_backend_find_printer (GtkPrintBackend *backend,
                                 const gchar *printer_name)
 {
-  g_return_val_if_fail (GTK_IS_PRINT_BACKEND (print_backend), NULL);
+  GtkPrintBackendPrivate *priv;
+  GtkPrinter *printer;
+  
+  g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
+
+  priv = backend->priv;
 
-  return GTK_PRINT_BACKEND_GET_IFACE (print_backend)->find_printer (print_backend, printer_name);
+  if (priv->printers)
+    printer = g_hash_table_lookup (priv->printers, printer_name);
+  else
+    printer = NULL;
 
+  return printer;  
 }
 
 void
-gtk_print_backend_print_stream (GtkPrintBackend *print_backend,
+gtk_print_backend_print_stream (GtkPrintBackend *backend,
                                 GtkPrintJob *job,
                                 gint data_fd,
                                 GtkPrintJobCompleteFunc callback,
                                 gpointer user_data,
                                GDestroyNotify dnotify)
 {
-  g_return_if_fail (GTK_IS_PRINT_BACKEND (print_backend));
-
-  GTK_PRINT_BACKEND_GET_IFACE (print_backend)->print_stream (print_backend,
-                                                            job,
-                                                            data_fd,
-                                                            callback,
-                                                            user_data,
-                                                            dnotify);
+  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
+
+  GTK_PRINT_BACKEND_GET_CLASS (backend)->print_stream (backend,
+                                                      job,
+                                                      data_fd,
+                                                      callback,
+                                                      user_data,
+                                                      dnotify);
+}
+
+static gboolean
+unref_at_idle_cb (gpointer data)
+{
+  g_object_unref (data);
+  return FALSE;
+}
+
+void
+gtk_print_backend_unref_at_idle (GtkPrintBackend *print_backend)
+{
+  g_idle_add (unref_at_idle_cb, print_backend);
+}
+
+void
+gtk_print_backend_destroy (GtkPrintBackend *print_backend)
+{
+  /* The lifecycle of print backends and printers are tied, such that
+     the backend owns the printers, but the printers also ref the backend.
+     This is so that if the app has a reference to a printer its backend
+     will be around. However, this results in a cycle, which we break
+     with this call, which causes the print backend to release its printers.
+  */
+  g_object_run_dispose (G_OBJECT (print_backend));
 }
 
 #define __GTK_PRINT_BACKEND_C__
index 4e2a05c4b3825cee014f0a9d243d37bf937ca7ba..fc48690ba3207e46259c8a76cbf381c7ff826f87 100644 (file)
@@ -39,7 +39,8 @@
 
 G_BEGIN_DECLS
 
-typedef struct _GtkPrintBackendIface  GtkPrintBackendIface;
+typedef struct _GtkPrintBackendClass    GtkPrintBackendClass;
+typedef struct _GtkPrintBackendPrivate  GtkPrintBackendPrivate;
 
 #define GTK_PRINT_BACKEND_ERROR (gtk_print_backend_error_quark ())
 
@@ -51,22 +52,28 @@ typedef enum
 
 GQuark     gtk_print_backend_error_quark      (void);
 
-#define GTK_TYPE_PRINT_BACKEND             (gtk_print_backend_get_type ())
-#define GTK_PRINT_BACKEND(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_BACKEND, GtkPrintBackend))
-#define GTK_IS_PRINT_BACKEND(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_BACKEND))
-#define GTK_PRINT_BACKEND_GET_IFACE(inst)  (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendIface))
+#define GTK_TYPE_PRINT_BACKEND                  (gtk_print_backend_get_type ())
+#define GTK_PRINT_BACKEND(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_BACKEND, GtkPrintBackend))
+#define GTK_PRINT_BACKEND_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendClass))
+#define GTK_IS_PRINT_BACKEND(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_BACKEND))
+#define GTK_IS_PRINT_BACKEND_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_BACKEND))
+#define GTK_PRINT_BACKEND_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendClass))
 
-struct _GtkPrintBackendIface
+struct _GtkPrintBackend
 {
-  GTypeInterface base_iface;
+  GObject parent_instance;
 
-  /* Global backend methods: */
-  GList      * (*get_printer_list) (GtkPrintBackend *printer_backend);
+  GtkPrintBackendPrivate *priv;
+};
 
-  GtkPrinter * (*find_printer) (GtkPrintBackend *print_backend,
-                                const gchar *printer_name);
-  void         (*print_stream) (GtkPrintBackend *print_backend,
-                                GtkPrintJob *job,
+struct _GtkPrintBackendClass
+{
+  GObjectClass parent_class;
+
+  /* Global backend methods: */
+  void (*request_printer_list) (GtkPrintBackend *backend);
+  void (*print_stream)         (GtkPrintBackend *backend,
+                               GtkPrintJob *job,
                                gint data_fd,
                                GtkPrintJobCompleteFunc callback,
                                gpointer user_data,
@@ -97,26 +104,49 @@ struct _GtkPrintBackendIface
                                                              double     *left,
                                                              double     *right);
 
-  /* Signals 
-   */
-  void (*printer_list_changed)   (void);
-  void (*printer_added)          (GtkPrinter *printer);
-  void (*printer_removed)        (GtkPrinter *printer);
-  void (*printer_status_changed) (GtkPrinter *printer);
+  /* Signals */
+  void (*printer_list_changed)   (GtkPrintBackend *backend);
+  void (*printer_list_done)      (GtkPrintBackend *backend);
+  void (*printer_added)          (GtkPrintBackend *backend,
+                                 GtkPrinter      *printer);
+  void (*printer_removed)        (GtkPrintBackend *backend,
+                                 GtkPrinter      *printer);
+  void (*printer_status_changed) (GtkPrintBackend *backend,
+                                 GtkPrinter      *printer);
+
+  /* Padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+  void (*_gtk_reserved5) (void);
+  void (*_gtk_reserved6) (void);
+  void (*_gtk_reserved7) (void);
 };
 
 GType   gtk_print_backend_get_type       (void) G_GNUC_CONST;
 
-GList      *gtk_print_backend_get_printer_list (GtkPrintBackend         *print_backend);
-GtkPrinter *gtk_print_backend_find_printer     (GtkPrintBackend         *print_backend,
-                                               const gchar             *printer_name);
-void        gtk_print_backend_print_stream     (GtkPrintBackend         *print_backend,
-                                               GtkPrintJob             *job,
-                                               gint                     data_fd,
-                                               GtkPrintJobCompleteFunc  callback,
-                                               gpointer                 user_data,
-                                               GDestroyNotify           dnotify);
-GList *     gtk_print_backend_load_modules     (void);
+GList      *gtk_print_backend_get_printer_list     (GtkPrintBackend         *print_backend);
+gboolean    gtk_print_backend_printer_list_is_done (GtkPrintBackend         *print_backend);
+GtkPrinter *gtk_print_backend_find_printer         (GtkPrintBackend         *print_backend,
+                                                   const gchar             *printer_name);
+void        gtk_print_backend_print_stream         (GtkPrintBackend         *print_backend,
+                                                   GtkPrintJob             *job,
+                                                   gint                     data_fd,
+                                                   GtkPrintJobCompleteFunc  callback,
+                                                   gpointer                 user_data,
+                                                   GDestroyNotify           dnotify);
+GList *     gtk_print_backend_load_modules         (void);
+void        gtk_print_backend_unref_at_idle        (GtkPrintBackend         *print_backend);
+void        gtk_print_backend_destroy              (GtkPrintBackend         *print_backend);
+
+/* Backend-only functions for GtkPrintBackend */
+
+void        gtk_print_backend_add_printer          (GtkPrintBackend         *print_backend,
+                                                   GtkPrinter              *printer);
+void        gtk_print_backend_remove_printer       (GtkPrintBackend         *print_backend,
+                                                   GtkPrinter              *printer);
+void        gtk_print_backend_set_list_done        (GtkPrintBackend         *backend);
 
 
 /* Backend-only functions for GtkPrinter */
index 4ae748cec0ab0e7db3d06318ce98328b6c15495e..e9a197cb9cd88d8da7d1d959ff6723761baadefd 100644 (file)
@@ -52,7 +52,6 @@ struct _GtkPrinterPrivate
   gchar *state_message;  
   gint job_count;
 
-  /* Not ref:ed, backend owns printer. */
   GtkPrintBackend *backend;
 };
 
@@ -215,6 +214,9 @@ gtk_printer_finalize (GObject *object)
   g_free (priv->state_message);
   g_free (priv->icon_name);
 
+  if (priv->backend)
+    g_object_unref (priv->backend);
+
   G_OBJECT_CLASS (gtk_printer_parent_class)->finalize (object);
 }
 
@@ -234,7 +236,7 @@ gtk_printer_set_property (GObject         *object,
       break;
     
     case PROP_BACKEND:
-      priv->backend = GTK_PRINT_BACKEND (g_value_get_object (value));
+      priv->backend = GTK_PRINT_BACKEND (g_value_dup_object (value));
       break;
 
     case PROP_IS_VIRTUAL:
@@ -340,16 +342,6 @@ gtk_printer_get_backend (GtkPrinter *printer)
   return printer->priv->backend;
 }
 
-void
-gtk_printer_set_backend (GtkPrinter      *printer,
-                        GtkPrintBackend *backend)
-{
-  g_return_if_fail (GTK_IS_PRINTER (printer));
-  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
-
-  printer->priv->backend = backend;
-}
-
 /**
  * gtk_printer_get_name:
  * @printer: a #GtkPrinter
@@ -663,8 +655,8 @@ gtk_printer_set_is_default (GtkPrinter *printer,
 void
 _gtk_printer_request_details (GtkPrinter *printer)
 {
-  GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
-  return backend_iface->printer_request_details (printer);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
+  return backend_class->printer_request_details (printer);
 }
 
 GtkPrinterOptionSet *
@@ -672,16 +664,16 @@ _gtk_printer_get_options (GtkPrinter       *printer,
                          GtkPrintSettings *settings,
                          GtkPageSetup     *page_setup)
 {
-  GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
-  return backend_iface->printer_get_options (printer, settings, page_setup);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
+  return backend_class->printer_get_options (printer, settings, page_setup);
 }
 
 gboolean
 _gtk_printer_mark_conflicts (GtkPrinter          *printer,
                             GtkPrinterOptionSet *options)
 {
-  GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
-  return backend_iface->printer_mark_conflicts (printer, options);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
+  return backend_class->printer_mark_conflicts (printer, options);
 }
   
 void
@@ -689,8 +681,8 @@ _gtk_printer_get_settings_from_options (GtkPrinter          *printer,
                                        GtkPrinterOptionSet *options,
                                        GtkPrintSettings    *settings)
 {
-  GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
-  return backend_iface->printer_get_settings_from_options (printer, options, settings);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
+  return backend_class->printer_get_settings_from_options (printer, options, settings);
 }
 
 void
@@ -699,8 +691,8 @@ _gtk_printer_prepare_for_print (GtkPrinter       *printer,
                                GtkPrintSettings *settings,
                                GtkPageSetup     *page_setup)
 {
-  GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
-  return backend_iface->printer_prepare_for_print (printer, print_job, settings, page_setup);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
+  return backend_class->printer_prepare_for_print (printer, print_job, settings, page_setup);
 }
 
 cairo_surface_t *
@@ -709,17 +701,17 @@ _gtk_printer_create_cairo_surface (GtkPrinter *printer,
                                   gdouble     height,
                                   gint        cache_fd)
 {
-  GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
 
-  return backend_iface->printer_create_cairo_surface (printer, width, height, cache_fd);
+  return backend_class->printer_create_cairo_surface (printer, width, height, cache_fd);
 }
 
 GList  *
 _gtk_printer_list_papers (GtkPrinter *printer)
 {
-  GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
 
-  return backend_iface->printer_list_papers (printer);
+  return backend_class->printer_list_papers (printer);
 }
 
 void
@@ -729,9 +721,28 @@ _gtk_printer_get_hard_margins (GtkPrinter *printer,
                               gdouble    *left,
                               gdouble    *right)
 {
-  GtkPrintBackendIface *backend_iface = GTK_PRINT_BACKEND_GET_IFACE (printer->priv->backend);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (printer->priv->backend);
 
-  backend_iface->printer_get_hard_margins (printer, top, bottom, left, right);
+  backend_class->printer_get_hard_margins (printer, top, bottom, left, right);
+}
+
+gint
+gtk_printer_compare (GtkPrinter *a, GtkPrinter *b)
+{
+  const char *name_a, *name_b;
+  
+  g_assert (GTK_IS_PRINTER (a) && GTK_IS_PRINTER (b));
+  
+  name_a = gtk_printer_get_name (a);
+  name_b = gtk_printer_get_name (b);
+  if (name_a == NULL  && name_b == NULL)
+    return 0;
+  else if (name_a == NULL)
+    return G_MAXINT;
+  else if (name_b == NULL)
+    return G_MININT;
+  else
+    return g_ascii_strcasecmp (name_a, name_b);
 }
 
 #define __GTK_PRINTER_C__
index 90a0e6b0ae657c8e4f1031ffab50d963b4b26758..6c9e056e15c6e34024e5362462ece897fc11361f 100644 (file)
@@ -78,6 +78,8 @@ gboolean                 gtk_printer_is_active         (GtkPrinter      *printer
 gboolean                 gtk_printer_is_virtual        (GtkPrinter      *printer);
 gboolean                 gtk_printer_is_default        (GtkPrinter      *printer);
 
+gint                     gtk_printer_compare           (GtkPrinter *a,
+                                                       GtkPrinter *b);
 
 G_END_DECLS
 
index cf38582dcc72906fab0d9005433713327c475603..2213967162305d590415e997ff4e6c98357633ff 100644 (file)
@@ -61,7 +61,8 @@ struct _GtkPrintOperationPrivate
                      GtkPageSetup *page_setup);
   void (*end_page) (GtkPrintOperation *operation,
                    GtkPrintContext *print_context);
-  void (*end_run) (GtkPrintOperation *operation);
+  void (*end_run) (GtkPrintOperation *operation,
+                  gboolean wait);
   GDestroyNotify free_platform_data;
 };
 
@@ -70,7 +71,8 @@ GtkPrintOperationResult _gtk_print_operation_platform_backend_run_dialog (GtkPri
                                                                          gboolean          *do_print,
                                                                          GError           **error);
 
-typedef void (* GtkPrintOperationPrintFunc) (GtkPrintOperation *op);
+typedef void (* GtkPrintOperationPrintFunc) (GtkPrintOperation *op,
+                                            gboolean wait);
 
 void _gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation          *op,
                                                             GtkWindow                  *parent,
index 4f74bf52ac9d63d6db30892ff680dc6196ff0f50..3b6f5561f5361b492c8ccbae642b2db2301c1f52 100644 (file)
@@ -42,8 +42,17 @@ typedef struct {
   GtkPrintJob *job;         /* the job we are sending to the printer */
   gulong job_status_changed_tag;
   GtkWindow *parent;        /* just in case we need to throw error dialogs */
+  GMainLoop *loop;
+  gboolean data_sent;
 } GtkPrintOperationUnix;
 
+typedef struct _PrinterFinder PrinterFinder;
+
+static void printer_finder_free (PrinterFinder *finder);
+static void find_printer        (const char    *printer,
+                                GFunc          func,
+                                gpointer       data);
+
 static void
 unix_start_page (GtkPrintOperation *op,
                 GtkPrintContext   *print_context,
@@ -100,18 +109,37 @@ unix_finish_send  (GtkPrintJob *job,
 
       gtk_window_present (GTK_WINDOW (edialog));
     }
+
+  op_unix->data_sent = TRUE;
+  if (op_unix->loop)
+    g_main_loop_quit (op_unix->loop);
 }
 
 static void
-unix_end_run (GtkPrintOperation *op)
+unix_end_run (GtkPrintOperation *op,
+             gboolean wait)
 {
   GtkPrintOperationUnix *op_unix = op->priv->platform_data;
+
+  if (wait)
+    op_unix->loop = g_main_loop_new (NULL, FALSE);
+  
   /* TODO: Check for error */
   gtk_print_job_send (op_unix->job,
                       unix_finish_send, 
                       op_unix, NULL,
                      NULL);
+
+  if (wait)
+    {
+      if (!op_unix->data_sent)
+       {
+         GDK_THREADS_LEAVE ();  
+         g_main_loop_run (op_unix->loop);
+         GDK_THREADS_ENTER ();  
+       }
+      g_main_loop_unref (op_unix->loop);
+    }
 }
 
 static void
@@ -154,6 +182,8 @@ typedef struct {
   GtkPrintOperationResult      result;
   GtkPrintOperationPrintFunc   print_cb;
   GDestroyNotify               destroy;
+  GtkWindow                   *parent;
+  GMainLoop                   *loop;
 } PrintResponseData;
 
 static void
@@ -166,41 +196,29 @@ print_response_data_free (gpointer data)
 }
 
 static void
-handle_print_response (GtkWidget *dialog,
-                      gint       response,
-                      gpointer   data)
+finish_print (PrintResponseData *rdata,
+             GtkPrinter *printer,
+             GtkPageSetup *page_setup,
+             GtkPrintSettings *settings)
 {
-  GtkPrintUnixDialog *pd = GTK_PRINT_UNIX_DIALOG (dialog);
-  PrintResponseData *rdata = data;
   GtkPrintOperation *op = rdata->op;
   GtkPrintOperationPrivate *priv = op->priv;
 
-  if (response == GTK_RESPONSE_OK)
+  priv->start_page = unix_start_page;
+  priv->end_page = unix_end_page;
+  priv->end_run = unix_end_run;
+  
+  if (rdata->do_print)
     {
       GtkPrintOperationUnix *op_unix;
-      GtkPrinter *printer;
-      GtkPrintSettings *settings;
-      GtkPageSetup *page_setup;
-
-      rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
-
-      printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (pd));
-      if (printer == NULL)
-       goto out;
-      
-      rdata->do_print = TRUE;
-
-      settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (pd));
-      page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (pd));
 
       gtk_print_operation_set_print_settings (op, settings);
-
+      
       op_unix = g_new0 (GtkPrintOperationUnix, 1);
       op_unix->job = gtk_print_job_new (priv->job_name,
                                        printer,
                                        settings,
                                        page_setup);
-      g_object_unref (settings);
   
       rdata->op->priv->surface = gtk_print_job_get_surface (op_unix->job, rdata->error);
       if (op->priv->surface == NULL)
@@ -216,7 +234,7 @@ handle_print_response (GtkWidget *dialog,
        g_signal_connect (op_unix->job, "status_changed",
                          G_CALLBACK (job_status_changed_cb), op);
       
-      op_unix->parent = gtk_window_get_transient_for (GTK_WINDOW (pd));
+      op_unix->parent = rdata->parent;
 
       priv->dpi_x = 72;
       priv->dpi_y = 72;
@@ -236,17 +254,11 @@ handle_print_response (GtkWidget *dialog,
       priv->manual_orientation = op_unix->job->rotate_to_orientation;
     } 
 
-  priv->start_page = unix_start_page;
-  priv->end_page = unix_end_page;
-  priv->end_run = unix_end_run;
-
  out:  
-  gtk_widget_destroy (GTK_WIDGET (pd));
-
   if (rdata->print_cb)
     {
       if (rdata->do_print)
-        rdata->print_cb (op); 
+        rdata->print_cb (op, FALSE); 
       else
        _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL); 
     }
@@ -255,6 +267,81 @@ handle_print_response (GtkWidget *dialog,
     rdata->destroy (rdata);
 }
 
+static void
+handle_print_response (GtkWidget *dialog,
+                      gint       response,
+                      gpointer   data)
+{
+  GtkPrintUnixDialog *pd = GTK_PRINT_UNIX_DIALOG (dialog);
+  PrintResponseData *rdata = data;
+  GtkPrintSettings *settings = NULL;
+  GtkPageSetup *page_setup = NULL;
+  GtkPrinter *printer = NULL;
+
+  if (response == GTK_RESPONSE_OK)
+    {
+      rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
+
+      printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (pd));
+      if (printer == NULL)
+       goto out;
+      
+      rdata->do_print = TRUE;
+
+      settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (pd));
+      page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (pd));
+    } 
+
+ out:  
+  finish_print (rdata, printer, page_setup, settings);
+
+  if (settings)
+    g_object_unref (settings);
+  
+  gtk_widget_destroy (GTK_WIDGET (pd));
+}
+
+
+static void
+found_printer (GtkPrinter *printer,
+              PrintResponseData *rdata)
+{
+  GtkPrintOperation *op = rdata->op;
+  GtkPrintOperationPrivate *priv = op->priv;
+  GtkPrintSettings *settings = NULL;
+  GtkPageSetup *page_setup = NULL;
+  
+  if (rdata->loop)
+    g_main_loop_quit (rdata->loop);
+
+  if (printer != NULL) {
+      rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
+
+      rdata->do_print = TRUE;
+
+      if (priv->print_settings)
+       settings = gtk_print_settings_copy (priv->print_settings);
+      else
+       settings = gtk_print_settings_new ();
+
+      gtk_print_settings_set_printer (settings,
+                                     gtk_printer_get_name (printer));
+      
+      if (priv->default_page_setup)
+       page_setup = gtk_page_setup_copy (priv->default_page_setup);
+      else
+       page_setup = gtk_page_setup_new ();
+  }
+  
+  finish_print (rdata, printer, page_setup, settings);
+
+  if (settings)
+    g_object_unref (settings);
+  
+  if (page_setup)
+    g_object_unref (page_setup);
+}
+
 void
 _gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation          *op,
                                                         GtkWindow                  *parent,
@@ -262,6 +349,7 @@ _gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation
 {
   GtkWidget *pd;
   PrintResponseData *rdata;
+  const char *printer_name;
 
   rdata = g_new (PrintResponseData, 1);
   rdata->op = g_object_ref (op);
@@ -269,15 +357,29 @@ _gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation
   rdata->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
   rdata->error = NULL;
   rdata->print_cb = print_cb;
+  rdata->parent = parent;
+  rdata->loop = NULL;
   rdata->destroy = print_response_data_free;
   
-  pd = get_print_dialog (op, parent);
-  gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
-
-  g_signal_connect (pd, "response", 
-                   G_CALLBACK (handle_print_response), rdata);
+  if (op->priv->show_dialog)
+    {
+      pd = get_print_dialog (op, parent);
+      gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
 
-  gtk_window_present (GTK_WINDOW (pd));
+      g_signal_connect (pd, "response", 
+                       G_CALLBACK (handle_print_response), rdata);
+      
+      gtk_window_present (GTK_WINDOW (pd));
+    }
+  else
+    {
+      printer_name = NULL;
+      if (op->priv->print_settings)
+       printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
+      
+      find_printer (printer_name,
+                   (GFunc) found_printer, rdata);
+    }
 }
 
 GtkPrintOperationResult
@@ -289,6 +391,7 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
   GtkWidget *pd;
   PrintResponseData rdata;
   gint response;  
+  const char *printer_name;
    
   rdata.op = op;
   rdata.do_print = FALSE;
@@ -296,14 +399,34 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
   rdata.error = error;
   rdata.print_cb = NULL;
   rdata.destroy = NULL;
+  rdata.parent = parent;
+  rdata.loop = NULL;
 
-  pd = get_print_dialog (op, parent);
+  if (op->priv->show_dialog)
+    {
+      pd = get_print_dialog (op, parent);
+      response = gtk_dialog_run (GTK_DIALOG (pd));
+      handle_print_response (pd, response, &rdata);
+    }
+  else
+    {
+      printer_name = NULL;
+      if (op->priv->print_settings)
+       printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
+      
+      rdata.loop = g_main_loop_new (NULL, FALSE);
+      find_printer (printer_name,
+                   (GFunc) found_printer, &rdata);
 
-  response = gtk_dialog_run (GTK_DIALOG (pd));
-  handle_print_response (pd, response, &rdata);
+      GDK_THREADS_LEAVE ();  
+      g_main_loop_run (rdata.loop);
+      GDK_THREADS_ENTER ();  
 
-  *do_print = rdata.do_print;
+      g_main_loop_unref (rdata.loop);
+    }
 
+  *do_print = rdata.do_print;
+  
   return rdata.result;
 }
 
@@ -448,6 +571,184 @@ gtk_print_run_page_setup_dialog_async (GtkWindow            *parent,
   gtk_window_present (GTK_WINDOW (dialog));
  }
 
+struct _PrinterFinder {
+  gboolean found_printer;
+  GFunc func;
+  gpointer data;
+  char *printer_name;
+  GList *backends;
+  guint timeout_tag;
+  GtkPrinter *printer;
+  GtkPrinter *default_printer;
+  GtkPrinter *first_printer;
+};
+
+static gboolean
+find_printer_idle (gpointer data)
+{
+  PrinterFinder *finder = data;
+  GtkPrinter *printer;
+
+  if (finder->printer != NULL)
+    printer = finder->printer;
+  else if (finder->default_printer != NULL)
+    printer = finder->default_printer;
+  else if (finder->first_printer != NULL)
+    printer = finder->first_printer;
+  else
+    printer = NULL;
+
+  finder->func (printer, finder->data);
+  
+  printer_finder_free (finder);
+
+  return FALSE;
+}
+
+static void
+printer_added_cb (GtkPrintBackend *backend, 
+                  GtkPrinter      *printer, 
+                 PrinterFinder   *finder)
+{
+  if (gtk_printer_is_virtual (printer) ||
+      finder->found_printer)
+    return;
+
+  if (finder->printer_name != NULL &&
+      strcmp (gtk_printer_get_name (printer), finder->printer_name) == 0)
+    {
+      finder->printer = g_object_ref (printer);
+      finder->found_printer = TRUE;
+    }
+  else if (finder->default_printer == NULL &&
+          gtk_printer_is_default (printer))
+    {
+      finder->default_printer = g_object_ref (printer);
+      if (finder->printer_name == NULL)
+       finder->found_printer = TRUE;
+    }
+  else
+    if (finder->first_printer == NULL)
+      finder->first_printer = g_object_ref (printer);
+  
+  if (finder->found_printer)
+    g_idle_add (find_printer_idle, finder);
+}
+
+static void
+printer_list_done_cb (GtkPrintBackend *backend, 
+                     PrinterFinder   *finder)
+{
+  finder->backends = g_list_remove (finder->backends, backend);
+  
+  g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder);
+  g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder);
+  
+  gtk_print_backend_destroy (backend);
+  g_object_unref (backend);
+
+  if (finder->backends == NULL && !finder->found_printer)
+    g_idle_add (find_printer_idle, finder);
+}
+
+static void
+find_printer_init (PrinterFinder *finder,
+                  GtkPrintBackend *backend)
+{
+  GList *list;
+  GList *node;
+
+  list = gtk_print_backend_get_printer_list (backend);
+
+  node = list;
+  while (node != NULL)
+    {
+      printer_added_cb (backend, node->data, finder);
+      node = node->next;
+
+      if (finder->found_printer)
+       break;
+    }
+
+  g_list_free (list);
+
+  if (gtk_print_backend_printer_list_is_done (backend))
+    {
+      finder->backends = g_list_remove (finder->backends, backend);
+      gtk_print_backend_destroy (backend);
+      g_object_unref (backend);
+    }
+  else
+    {
+      g_signal_connect (backend, 
+                       "printer-added", 
+                       (GCallback) printer_added_cb, 
+                       finder);
+      g_signal_connect (backend, 
+                       "printer-list-done", 
+                       (GCallback) printer_list_done_cb, 
+                       finder);
+    }
+
+}
+
+static void
+printer_finder_free (PrinterFinder *finder)
+{
+  GList *l;
+  
+  g_free (finder->printer_name);
+  
+  if (finder->printer)
+    g_object_unref (finder->printer);
+  
+  if (finder->default_printer)
+    g_object_unref (finder->default_printer);
+  
+  if (finder->first_printer)
+    g_object_unref (finder->first_printer);
+
+  for (l = finder->backends; l != NULL; l = l->next)
+    {
+      GtkPrintBackend *backend = l->data;
+      g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder);
+      g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder);
+      gtk_print_backend_destroy (backend);
+      g_object_unref (backend);
+    }
+  
+  g_list_free (finder->backends);
+  
+  g_free (finder);
+}
+
+static void 
+find_printer (const char *printer,
+             GFunc func,
+             gpointer data)
+{
+  GList *node, *next;
+  PrinterFinder *finder;
+
+  finder = g_new0 (PrinterFinder, 1);
+
+  finder->printer_name = g_strdup (printer);
+  finder->func = func;
+  finder->data = data;
+  
+  finder->backends = NULL;
+  if (g_module_supported ())
+    finder->backends = gtk_print_backend_load_modules ();
+
+  for (node = finder->backends; !finder->found_printer && node != NULL; node = next)
+    {
+      next = node->next;
+      find_printer_init (finder, GTK_PRINT_BACKEND (node->data));
+    }
+
+  if (finder->backends == NULL && !finder->found_printer)
+    g_idle_add (find_printer_idle, finder);
+}
 
 #define __GTK_PRINT_OPERATION_UNIX_C__
 #include "gtkaliasdef.c"
index cd52b8eb1fae9bbd607747dbd3df233edf389d4d..998717d753304db1dc48327c5e5f5dbcb0ddedce 100644 (file)
@@ -1115,7 +1115,8 @@ pdf_end_page (GtkPrintOperation *op,
 }
 
 static void
-pdf_end_run (GtkPrintOperation *op)
+pdf_end_run (GtkPrintOperation *op,
+            gboolean wait)
 {
   GtkPrintOperationPrivate *priv = op->priv;
 
@@ -1161,7 +1162,8 @@ run_pdf (GtkPrintOperation  *op,
 }
 
 static void
-print_pages (GtkPrintOperation *op)
+print_pages (GtkPrintOperation *op,
+            gboolean wait)
 {
   GtkPrintOperationPrivate *priv = op->priv;
   int page, range;
@@ -1289,8 +1291,7 @@ print_pages (GtkPrintOperation *op)
   g_object_unref (initial_page_setup);
 
   cairo_surface_finish (priv->surface);
-  priv->end_run (op);
-
+  priv->end_run (op, wait);
 }
 
 /**
@@ -1343,7 +1344,7 @@ gtk_print_operation_run (GtkPrintOperation  *op,
                                                               &do_print,
                                                               error);
   if (do_print)
-    print_pages (op);
+    print_pages (op, TRUE);
   else 
     _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
 
@@ -1384,7 +1385,7 @@ gtk_print_operation_run_async (GtkPrintOperation *op,
     {
       run_pdf (op, parent, &do_print, NULL);
       if (do_print)
-       print_pages (op);
+       print_pages (op, FALSE);
       else 
        _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
     }
index f2cdd8040a490857aff29b8d05fa24a5548ccd88..59cf75321beb75fbf0a1709889345eda85729724 100644 (file)
@@ -73,6 +73,15 @@ static void unschedule_idle_mark_conflicts     (GtkPrintUnixDialog *dialog);
 static void selected_printer_changed           (GtkTreeSelection   *selection,
                                                GtkPrintUnixDialog *dialog);
 static void clear_per_printer_ui               (GtkPrintUnixDialog *dialog);
+static void printer_added_cb                   (GtkPrintBackend    *backend,
+                                               GtkPrinter         *printer,
+                                               GtkPrintUnixDialog *dialog);
+static void printer_removed_cb                 (GtkPrintBackend    *backend,
+                                               GtkPrinter         *printer,
+                                               GtkPrintUnixDialog *dialog);
+static void printer_status_cb                  (GtkPrintBackend    *backend,
+                                               GtkPrinter         *printer,
+                                               GtkPrintUnixDialog *dialog);
 
 enum {
   PROP_0,
@@ -281,6 +290,8 @@ gtk_print_unix_dialog_finalize (GObject *object)
 {
   GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
   GtkPrintUnixDialogPrivate *priv = dialog->priv;
+  GtkPrintBackend *backend;
+  GList *node;
 
   unschedule_idle_mark_conflicts (dialog);
 
@@ -339,6 +350,21 @@ gtk_print_unix_dialog_finalize (GObject *object)
   g_free (priv->format_for_printer);
   priv->format_for_printer = NULL;
 
+  for (node = priv->print_backends; node != NULL; node = node->next)
+    {
+      backend = GTK_PRINT_BACKEND (node->data);
+
+      g_signal_handlers_disconnect_by_func (backend, printer_added_cb, dialog);
+      g_signal_handlers_disconnect_by_func (backend, printer_removed_cb, dialog);
+      g_signal_handlers_disconnect_by_func (backend, printer_status_cb, dialog);
+
+      gtk_print_backend_destroy (backend);
+      g_object_unref (backend);
+    }
+  
+  g_list_free (priv->print_backends);
+  priv->print_backends = NULL;
+  
   G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->finalize (object);
 }
 
@@ -1164,6 +1190,7 @@ selected_printer_changed (GtkTreeSelection   *selection,
        g_signal_connect (printer, "details-acquired",
                          G_CALLBACK (printer_details_acquired), dialog);
       _gtk_printer_request_details (printer);
+      g_object_unref (printer);
       return;
     }
   
index 458e1c421928b7553817264d5a8b888e6e5b7c59..2ebf4a785f4894ac63903a0398812147d52af4de 100644 (file)
@@ -242,6 +242,26 @@ gtk_cups_request_ipp_add_string (GtkCupsRequest *request,
                 value);
 }
 
+void            
+gtk_cups_request_ipp_add_strings (GtkCupsRequest *request,
+                                 ipp_tag_t group,
+                                 ipp_tag_t tag,
+                                 const char *name,
+                                 int num_values,
+                                 const char *charset,
+                                 const char * const *values)
+{
+  ippAddStrings (request->ipp_request,
+                group,
+                tag,
+                name,
+                num_values,
+                charset,
+                values);
+}
+
+
+
 typedef struct
 {
   const char   *name;
index f49cd2e9bcdfdf3e331539cd9f51be1ca146f01a..88fb8810f29f3935c1422e739592148cdcb32aa1 100644 (file)
@@ -109,6 +109,13 @@ void             gtk_cups_request_ipp_add_string  (GtkCupsRequest     *request,
                                                   const char         *name,
                                                   const char         *charset,
                                                   const char         *value);
+void             gtk_cups_request_ipp_add_strings (GtkCupsRequest     *request,
+                                                  ipp_tag_t           group,
+                                                  ipp_tag_t           tag,
+                                                  const char         *name,
+                                                  int                 num_values,
+                                                  const char         *charset,
+                                                  const char * const *values);
 gboolean         gtk_cups_request_read_write      (GtkCupsRequest     *request);
 GtkCupsPollState gtk_cups_request_get_poll_state  (GtkCupsRequest     *request);
 void             gtk_cups_request_free            (GtkCupsRequest     *request);
index 0e10c275b0fb7d2dfb16dcda83223e38961a4107..13bdfdb0d4168660d649776b4a07ff8a05e96320 100644 (file)
@@ -89,14 +89,12 @@ typedef struct
 
 struct _GtkPrintBackendCupsClass
 {
-  GObjectClass parent_class;
+  GtkPrintBackendClass parent_class;
 };
 
 struct _GtkPrintBackendCups
 {
-  GObject parent_instance;
-
-  GHashTable *printers;
+  GtkPrintBackend parent_instance;
 
   char *default_printer;
   
@@ -108,10 +106,10 @@ struct _GtkPrintBackendCups
 static GObjectClass *backend_parent_class;
 
 static void                 gtk_print_backend_cups_class_init      (GtkPrintBackendCupsClass          *class);
-static void                 gtk_print_backend_cups_iface_init      (GtkPrintBackendIface              *iface);
 static void                 gtk_print_backend_cups_init            (GtkPrintBackendCups               *impl);
 static void                 gtk_print_backend_cups_finalize        (GObject                           *object);
-static GList *              cups_get_printer_list              (GtkPrintBackend                    *print_backend);
+static void                 gtk_print_backend_cups_dispose         (GObject                           *object);
+static void                 cups_get_printer_list                  (GtkPrintBackend                   *print_backend);
 static void                 cups_request_execute                   (GtkPrintBackendCups               *print_backend,
                                                                    GtkCupsRequest                    *request,
                                                                    GtkPrintCupsResponseCallbackFunc   callback,
@@ -145,6 +143,17 @@ static void                 cups_begin_polling_info                (GtkPrintBack
                                                                    GtkPrintJob                       *job,
                                                                    int                                job_id);
 static gboolean             cups_job_info_poll_timeout             (gpointer                           user_data);
+static void                 gtk_print_backend_cups_print_stream    (GtkPrintBackend                   *backend,
+                                                                   GtkPrintJob                       *job,
+                                                                   gint                               data_fd,
+                                                                   GtkPrintJobCompleteFunc            callback,
+                                                                   gpointer                           user_data,
+                                                                   GDestroyNotify                     dnotify);
+static cairo_surface_t *    cups_printer_create_cairo_surface      (GtkPrinter                        *printer,
+                                                                   gdouble                            width,
+                                                                   gdouble                            height,
+                                                                   gint                               cache_fd);
+
 
 static void
 gtk_print_backend_cups_register_type (GTypeModule *module)
@@ -164,21 +173,10 @@ gtk_print_backend_cups_register_type (GTypeModule *module)
        (GInstanceInitFunc) gtk_print_backend_cups_init
       };
 
-      static const GInterfaceInfo print_backend_info =
-      {
-       (GInterfaceInitFunc) gtk_print_backend_cups_iface_init, /* interface_init */
-       NULL,                                                 /* interface_finalize */
-       NULL                                                  /* interface_data */
-      };
-
       print_backend_cups_type = g_type_module_register_type (module,
-                                                             G_TYPE_OBJECT,
+                                                             GTK_TYPE_PRINT_BACKEND,
                                                             "GtkPrintBackendCups",
                                                             &print_backend_cups_info, 0);
-      g_type_module_add_interface (module,
-                                   print_backend_cups_type,
-                                  GTK_TYPE_PRINT_BACKEND,
-                                  &print_backend_info);
     }
 }
 
@@ -229,10 +227,23 @@ static void
 gtk_print_backend_cups_class_init (GtkPrintBackendCupsClass *class)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_CLASS (class);
 
   backend_parent_class = g_type_class_peek_parent (class);
 
   gobject_class->finalize = gtk_print_backend_cups_finalize;
+  gobject_class->dispose = gtk_print_backend_cups_dispose;
+
+  backend_class->request_printer_list = cups_get_printer_list; 
+  backend_class->print_stream = gtk_print_backend_cups_print_stream;
+  backend_class->printer_request_details = cups_printer_request_details;
+  backend_class->printer_create_cairo_surface = cups_printer_create_cairo_surface;
+  backend_class->printer_get_options = cups_printer_get_options;
+  backend_class->printer_mark_conflicts = cups_printer_mark_conflicts;
+  backend_class->printer_get_settings_from_options = cups_printer_get_settings_from_options;
+  backend_class->printer_prepare_for_print = cups_printer_prepare_for_print;
+  backend_class->printer_list_papers = cups_printer_list_papers;
+  backend_class->printer_get_hard_margins = cups_printer_get_hard_margins;
 }
 
 static cairo_status_t
@@ -272,18 +283,6 @@ cups_printer_create_cairo_surface (GtkPrinter *printer,
   return surface;
 }
 
-static GtkPrinter *
-gtk_print_backend_cups_find_printer (GtkPrintBackend *print_backend,
-                                     const gchar *printer_name)
-{
-  GtkPrintBackendCups *cups_print_backend;
-
-  cups_print_backend = GTK_PRINT_BACKEND_CUPS (print_backend);
-  
-  return (GtkPrinter *) g_hash_table_lookup (cups_print_backend->printers, 
-                                                  printer_name);  
-}
-
 typedef struct {
   GtkPrintJobCompleteFunc callback;
   GtkPrintJob *job;
@@ -416,31 +415,11 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend *print_backend,
 }
 
 
-static void
-gtk_print_backend_cups_iface_init (GtkPrintBackendIface *iface)
-{
-  iface->get_printer_list = cups_get_printer_list; 
-  iface->find_printer = gtk_print_backend_cups_find_printer;
-  iface->print_stream = gtk_print_backend_cups_print_stream;
-  iface->printer_request_details = cups_printer_request_details;
-  iface->printer_create_cairo_surface = cups_printer_create_cairo_surface;
-  iface->printer_get_options = cups_printer_get_options;
-  iface->printer_mark_conflicts = cups_printer_mark_conflicts;
-  iface->printer_get_settings_from_options = cups_printer_get_settings_from_options;
-  iface->printer_prepare_for_print = cups_printer_prepare_for_print;
-  iface->printer_list_papers = cups_printer_list_papers;
-  iface->printer_get_hard_margins = cups_printer_get_hard_margins;
-}
-
 static void
 gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups)
 {
   backend_cups->list_printers_poll = 0;  
   backend_cups->list_printers_pending = FALSE;
-  backend_cups->printers = g_hash_table_new_full (g_str_hash, 
-                                                  g_str_equal, 
-                                                 (GDestroyNotify) g_free,
-                                                 (GDestroyNotify) g_object_unref);
 
   cups_request_default_printer (backend_cups);
 }
@@ -452,18 +431,27 @@ gtk_print_backend_cups_finalize (GObject *object)
 
   backend_cups = GTK_PRINT_BACKEND_CUPS (object);
 
-  if (backend_cups->list_printers_poll > 0)
-    g_source_remove (backend_cups->list_printers_poll);
-
-  if (backend_cups->printers)
-    g_hash_table_unref (backend_cups->printers);
-
   g_free (backend_cups->default_printer);
   backend_cups->default_printer = NULL;
   
   backend_parent_class->finalize (object);
 }
 
+static void
+gtk_print_backend_cups_dispose (GObject *object)
+{
+  GtkPrintBackendCups *backend_cups;
+
+  backend_cups = GTK_PRINT_BACKEND_CUPS (object);
+
+  if (backend_cups->list_printers_poll > 0)
+    g_source_remove (backend_cups->list_printers_poll);
+  backend_cups->list_printers_poll = 0;
+  
+  backend_parent_class->dispose (object);
+}
+
+
 static gboolean
 cups_dispatch_watch_check (GSource *source)
 {
@@ -514,13 +502,12 @@ cups_dispatch_watch_check (GSource *source)
 
 static gboolean
 cups_dispatch_watch_prepare (GSource *source,
-                              gint *timeout_)
+                            gint *timeout_)
 {
   GtkPrintCupsDispatchWatch *dispatch;
 
   dispatch = (GtkPrintCupsDispatchWatch *) source;
  
-
   *timeout_ = -1;
   
   return gtk_cups_request_read_write (dispatch->request);
@@ -528,8 +515,8 @@ cups_dispatch_watch_prepare (GSource *source,
 
 static gboolean
 cups_dispatch_watch_dispatch (GSource *source,
-                               GSourceFunc callback,
-                               gpointer user_data)
+                             GSourceFunc callback,
+                             gpointer user_data)
 {
   GtkPrintCupsDispatchWatch *dispatch;
   GtkPrintCupsResponseCallbackFunc ep_callback;  
@@ -548,7 +535,6 @@ cups_dispatch_watch_dispatch (GSource *source,
 
   ep_callback (GTK_PRINT_BACKEND (dispatch->backend), result, user_data);
 
-  g_source_unref (source); 
   return FALSE;
 }
 
@@ -563,7 +549,11 @@ cups_dispatch_watch_finalize (GSource *source)
 
   if (dispatch->backend)
     {
-      g_object_unref (dispatch->backend);
+      /* We need to unref this at idle time, because it might be the
+        last reference to this module causing the code to be
+        unloaded (including this particular function!)
+      */
+      gtk_print_backend_unref_at_idle (GTK_PRINT_BACKEND (dispatch->backend));
       dispatch->backend = NULL;
     }
 
@@ -588,7 +578,7 @@ cups_request_execute (GtkPrintBackendCups *print_backend,
                       GError **err)
 {
   GtkPrintCupsDispatchWatch *dispatch;
-  
+
   dispatch = (GtkPrintCupsDispatchWatch *) g_source_new (&_cups_dispatch_watch_funcs, 
                                                          sizeof (GtkPrintCupsDispatchWatch));
 
@@ -599,10 +589,11 @@ cups_request_execute (GtkPrintBackendCups *print_backend,
   g_source_set_callback ((GSource *) dispatch, (GSourceFunc) callback, user_data, notify);
 
   g_source_attach ((GSource *) dispatch, NULL);
+  g_source_unref ((GSource *) dispatch);
 }
 
 static void
-cups_request_printer_info_cb (GtkPrintBackendCups *print_backend,
+cups_request_printer_info_cb (GtkPrintBackendCups *backend,
                               GtkCupsResult *result,
                               gpointer user_data)
 {
@@ -611,40 +602,29 @@ cups_request_printer_info_cb (GtkPrintBackendCups *print_backend,
   gchar *printer_name;
   GtkPrinterCups *cups_printer;
   GtkPrinter *printer;
-  gchar *printer_uri;
-  gchar *member_printer_uri;
   gchar *loc;
   gchar *desc;
   gchar *state_msg;
   int job_count;
-
-  char uri[HTTP_MAX_URI],      /* Printer URI */
-       method[HTTP_MAX_URI],   /* Method/scheme name */
-       username[HTTP_MAX_URI], /* Username:password */
-       hostname[HTTP_MAX_URI], /* Hostname */
-       resource[HTTP_MAX_URI]; /* Resource name */
-  int  port;                   /* Port number */
   gboolean status_changed;  
 
-  g_assert (GTK_IS_PRINT_BACKEND_CUPS (print_backend));
-
-  printer_uri = NULL;
-  member_printer_uri = NULL;
+  g_assert (GTK_IS_PRINT_BACKEND_CUPS (backend));
 
   printer_name = (gchar *)user_data;
-  cups_printer = (GtkPrinterCups *) g_hash_table_lookup (print_backend->printers, printer_name);
+  printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (backend),
+                                           printer_name);
 
-  if (!cups_printer)
+  if (!printer)
     return;
 
-  printer = GTK_PRINTER (cups_printer);
+  cups_printer = GTK_PRINTER_CUPS (printer);
   
   if (gtk_cups_result_is_error (result))
     {
       if (gtk_printer_is_new (printer))
        {
-         g_hash_table_remove (print_backend->printers,
-                              printer_name);
+         gtk_print_backend_remove_printer (GTK_PRINT_BACKEND (backend),
+                                           printer);
          return;
        }
       else
@@ -656,8 +636,6 @@ cups_request_printer_info_cb (GtkPrintBackendCups *print_backend,
   /* TODO: determine printer type and use correct icon */
   gtk_printer_set_icon_name (printer, "printer");
   
-  cups_printer->device_uri = g_strdup_printf ("/printers/%s", printer_name);
-
   state_msg = "";
   loc = "";
   desc = "";
@@ -670,8 +648,6 @@ cups_request_printer_info_cb (GtkPrintBackendCups *print_backend,
       _CUPS_MAP_ATTR_STR (attr, loc, "printer-location");
       _CUPS_MAP_ATTR_STR (attr, desc, "printer-info");
       _CUPS_MAP_ATTR_STR (attr, state_msg, "printer-state-message");
-      _CUPS_MAP_ATTR_STR (attr, printer_uri, "printer-uri-supported");
-      _CUPS_MAP_ATTR_STR (attr, member_printer_uri, "member-uris");
       _CUPS_MAP_ATTR_INT (attr, cups_printer->state, "printer-state");
       _CUPS_MAP_ATTR_INT (attr, job_count, "queued-job-count");
     }
@@ -679,53 +655,15 @@ cups_request_printer_info_cb (GtkPrintBackendCups *print_backend,
   /* if we got a member_printer_uri then this printer is part of a class
      so use member_printer_uri, else user printer_uri */
 
-  if (cups_printer->printer_uri)
-    g_free (cups_printer->printer_uri);
-
-  if (member_printer_uri)
-    {
-      g_free (printer_uri);
-      cups_printer->printer_uri = member_printer_uri;
-    }
-  else
-    cups_printer->printer_uri = printer_uri;
-
   status_changed = gtk_printer_set_job_count (printer, job_count);
   
   status_changed |= gtk_printer_set_location (printer, loc);
   status_changed |= gtk_printer_set_description (printer, desc);
   status_changed |= gtk_printer_set_state_message (printer, state_msg);
 
-#if (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 2) || CUPS_VERSION_MAJOR > 1
-  httpSeparateURI (HTTP_URI_CODING_ALL, cups_printer->printer_uri, 
-                   method, sizeof (method), 
-                   username, sizeof (username),
-                   hostname, sizeof (hostname),
-                  &port, 
-                   resource, sizeof (resource));
-
-#else
-  httpSeparate (cups_printer->printer_uri, 
-                method, 
-                username, 
-                hostname,
-               &port, 
-                resource);
-#endif
-
-  gethostname(uri, sizeof(uri));
-
-  if (strcasecmp(uri, hostname) == 0)
-    strcpy(hostname, "localhost");
-
-  if (cups_printer->hostname)
-    g_free (cups_printer->hostname);
-
-  cups_printer->hostname = g_strdup (hostname);
-  cups_printer->port = port;
-
   if (status_changed)
-    g_signal_emit_by_name (GTK_PRINT_BACKEND (print_backend), "printer-status-changed", printer); 
+    g_signal_emit_by_name (GTK_PRINT_BACKEND (backend),
+                          "printer-status-changed", printer); 
 }
 
 static void
@@ -735,6 +673,14 @@ cups_request_printer_info (GtkPrintBackendCups *print_backend,
   GError *error;
   GtkCupsRequest *request;
   gchar *printer_uri;
+  static const char * const pattrs[] = /* Attributes we're interested in */
+    {
+      "printer-location",
+      "printer-info",
+      "printer-state-message",
+      "printer-state",
+      "queued-job-count"
+    };
 
   error = NULL;
 
@@ -752,6 +698,10 @@ cups_request_printer_info (GtkPrintBackendCups *print_backend,
 
   g_free (printer_uri);
 
+  gtk_cups_request_ipp_add_strings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+                                   "requested-attributes", G_N_ELEMENTS (pattrs),
+                                   NULL, pattrs);
   cups_request_execute (print_backend,
                         request,
                         (GtkPrintCupsResponseCallbackFunc) cups_request_printer_info_cb,
@@ -922,82 +872,22 @@ cups_begin_polling_info (GtkPrintBackendCups *print_backend,
   cups_request_job_info (data);
 }
 
-static gint
-printer_cmp (GtkPrinter *a, GtkPrinter *b)
-{
-  const char *name_a, *name_b;
-  g_assert (GTK_IS_PRINTER (a) && GTK_IS_PRINTER (b));
-
-  name_a = gtk_printer_get_name (a);
-  name_b = gtk_printer_get_name (b);
-  if (name_a == NULL  && name_b == NULL)
-    return 0;
-  else if (name_a == NULL)
-    return G_MAXINT;
-  else if (name_b == NULL)
-    return G_MININT;
-  else
-    return g_ascii_strcasecmp (name_a, name_b);
-}
-
 static void
-printer_hash_to_sorted_active_list (const gchar *key,
-                                    gpointer value,
-                                    GList **out_list)
+mark_printer_inactive (GtkPrinter *printer, 
+                       GtkPrintBackend *backend)
 {
-  GtkPrinter *printer;
-
-  printer = GTK_PRINTER (value);
-
-  if (gtk_printer_get_name (printer) == NULL)
-    return;
-
-  if (!gtk_printer_is_active (printer))
-    return;
-
-  *out_list = g_list_insert_sorted (*out_list, value, (GCompareFunc) printer_cmp);
+  gtk_printer_set_is_active (printer, FALSE);
+  g_signal_emit_by_name (backend,
+                        "printer-removed", printer);
 }
 
-static void
-printer_hash_to_sorted_active_name_list (const gchar *key,
-                                         gpointer value,
-                                         GList **out_list)
+static gint
+find_printer (GtkPrinter *printer, const char *find_name)
 {
-  GtkPrinter *printer;
-
-  printer = GTK_PRINTER (value);
-
-
-  if (gtk_printer_get_name (printer) == NULL)
-    return;
-
-  if (!gtk_printer_is_active (printer))
-    return;
+  const char *printer_name;
 
-  if (gtk_printer_is_active (printer))
-    *out_list = g_list_insert_sorted (*out_list,
-                                     (char *)gtk_printer_get_name (printer),
-                                     g_str_equal);
-}
-
-static void
-mark_printer_inactive (const gchar *printer_name, 
-                       GtkPrintBackendCups *cups_backend)
-{
-  GtkPrinter *printer;
-  GHashTable *printer_hash;
-
-  printer_hash = cups_backend->printers;
-
-  printer = (GtkPrinter *) g_hash_table_lookup (printer_hash, 
-                                                printer_name);
-
-  if (printer == NULL)
-    return;
-
-  gtk_printer_set_is_active (printer, FALSE);
-
-  g_signal_emit_by_name (GTK_PRINT_BACKEND (cups_backend), "printer-removed", printer);
+  printer_name = gtk_printer_get_name (printer);
+  return g_ascii_strcasecmp (printer_name, find_name);
 }
 
 static void
@@ -1021,51 +911,122 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
       g_warning ("Error getting printer list: %s", gtk_cups_result_get_error_string (result));
       return;
     }
-
+  
   /* gether the names of the printers in the current queue
      so we may check to see if they were removed */
-  removed_printer_checklist = NULL;
-  if (cups_backend->printers != NULL)
-    g_hash_table_foreach (cups_backend->printers,
-                          (GHFunc) printer_hash_to_sorted_active_name_list,
-                          &removed_printer_checklist);
-
+  removed_printer_checklist = gtk_print_backend_get_printer_list (GTK_PRINT_BACKEND (cups_backend));
+                                                                 
   response = gtk_cups_result_get_response (result);
 
-  attr = ippFindAttribute (response, "printer-name", IPP_TAG_NAME);
 
-  while (attr) 
+  for (attr = response->attrs; attr != NULL; attr = attr->next)
     {
-      GtkPrinterCups *cups_printer;
       GtkPrinter *printer;
       const gchar *printer_name;
+      const char *printer_uri;
+      const char *member_uris;
       GList *node;
+      
+      /*
+      * Skip leading attributes until we hit a printer...
+      */
+      while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
+        attr = attr->next;
+
+      if (attr == NULL)
+        break;
+
+      printer_name = NULL;
+      printer_uri = NULL;
+      member_uris = NULL;
+      while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
+      {
+        if (!strcmp(attr->name, "printer-name") &&
+           attr->value_tag == IPP_TAG_NAME)
+         printer_name = attr->values[0].string.text;
+       else if (!strcmp(attr->name, "printer-uri-supported") &&
+                attr->value_tag == IPP_TAG_URI)
+         printer_uri = attr->values[0].string.text;
+       else if (!strcmp(attr->name, "member-uris") &&
+                attr->value_tag == IPP_TAG_URI)
+         member_uris = attr->values[0].string.text;
+
+        attr = attr->next;
+      }
 
-      printer_name = attr->values[0].string.text;
+      if (printer_name == NULL ||
+         (printer_uri == NULL && member_uris == NULL))
+      {
+        if (attr == NULL)
+         break;
+       else
+          continue;
+      }
+   
       /* remove name from checklist if it was found */
-      node = g_list_find_custom (removed_printer_checklist, printer_name, (GCompareFunc) g_ascii_strcasecmp);
+      node = g_list_find_custom (removed_printer_checklist, printer_name, (GCompareFunc) find_printer);
       removed_printer_checklist = g_list_delete_link (removed_printer_checklist, node);
  
-      cups_printer = (GtkPrinterCups *) g_hash_table_lookup (cups_backend->printers, 
-                                                             printer_name);
-      printer = cups_printer ? GTK_PRINTER (cups_printer) : NULL;
-
-      if (!cups_printer)
+      printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (cups_backend), printer_name);
+      if (!printer)
         {
+         GtkPrinterCups *cups_printer;
+         char uri[HTTP_MAX_URI],       /* Printer URI */
+           method[HTTP_MAX_URI],       /* Method/scheme name */
+           username[HTTP_MAX_URI],     /* Username:password */
+           hostname[HTTP_MAX_URI],     /* Hostname */
+           resource[HTTP_MAX_URI];     /* Resource name */
+         int  port;                    /* Port number */
+         
           list_has_changed = TRUE;
-         cups_printer = gtk_printer_cups_new (attr->values[0].string.text,
+         cups_printer = gtk_printer_cups_new (printer_name,
                                               GTK_PRINT_BACKEND (cups_backend));
-         printer = GTK_PRINTER (cups_printer);
 
+         cups_printer->device_uri = g_strdup_printf ("/printers/%s", printer_name);
+
+         if (member_uris)
+           {
+             cups_printer->printer_uri = g_strdup (member_uris);
+           }
+         else
+           cups_printer->printer_uri = g_strdup (printer_uri);
+
+#if (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 2) || CUPS_VERSION_MAJOR > 1
+         httpSeparateURI (HTTP_URI_CODING_ALL, cups_printer->printer_uri, 
+                          method, sizeof (method), 
+                          username, sizeof (username),
+                          hostname, sizeof (hostname),
+                          &port, 
+                          resource, sizeof (resource));
+
+#else
+         httpSeparate (cups_printer->printer_uri, 
+                       method, 
+                       username, 
+                       hostname,
+                       &port, 
+                       resource);
+#endif
+
+         gethostname(uri, sizeof(uri));
+         if (strcasecmp(uri, hostname) == 0)
+           strcpy(hostname, "localhost");
+
+         cups_printer->hostname = g_strdup (hostname);
+         cups_printer->port = port;
+         
+         printer = GTK_PRINTER (cups_printer);
+         
          if (cups_backend->default_printer != NULL &&
              strcmp (cups_backend->default_printer, gtk_printer_get_name (printer)) == 0)
            gtk_printer_set_is_default (printer, TRUE);
 
-          g_hash_table_insert (cups_backend->printers,
-                               g_strdup (gtk_printer_get_name (printer)), 
-                               cups_printer);
+         
+         gtk_print_backend_add_printer (GTK_PRINT_BACKEND (cups_backend), printer);
         }
-    
+      else
+       g_object_ref (printer);
+
       if (!gtk_printer_is_active (printer))
         {
          gtk_printer_set_is_active (printer, TRUE);
@@ -1083,25 +1044,29 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
         }
 
       cups_request_printer_info (cups_backend, gtk_printer_get_name (printer));
-      
-      attr = ippFindNextAttribute (response, 
-                                   "printer-name",
-                                   IPP_TAG_NAME);
-    }
 
-    /* look at the removed printers checklist and mark any printer
-       as inactive if it is in the list, emitting a printer_removed signal */
+      /* The ref is held by GtkPrintBackend, in add_printer() */
+      g_object_unref (printer);
 
-    if (removed_printer_checklist != NULL)
-      {
-        g_list_foreach (removed_printer_checklist, (GFunc) mark_printer_inactive, cups_backend);
-        g_list_free (removed_printer_checklist);
-        list_has_changed = TRUE;
-      }
-
-    if (list_has_changed)
-       g_signal_emit_by_name (GTK_PRINT_BACKEND (cups_backend), "printer-list-changed");
+      
+      if (attr == NULL)
+        break;
+    }
 
+  /* look at the removed printers checklist and mark any printer
+     as inactive if it is in the list, emitting a printer_removed signal */
+  if (removed_printer_checklist != NULL)
+    {
+      g_list_foreach (removed_printer_checklist, (GFunc) mark_printer_inactive,
+                     GTK_PRINT_BACKEND (cups_backend));
+      g_list_free (removed_printer_checklist);
+      list_has_changed = TRUE;
+    }
+  
+  if (list_has_changed)
+    g_signal_emit_by_name (GTK_PRINT_BACKEND (cups_backend), "printer-list-changed");
+  
+  gtk_print_backend_set_list_done (GTK_PRINT_BACKEND (cups_backend));
 }
 
 static gboolean
@@ -1109,7 +1074,13 @@ cups_request_printer_list (GtkPrintBackendCups *cups_backend)
 {
   GError *error;
   GtkCupsRequest *request;
-
+  static const char * const pattrs[] = /* Attributes we're interested in */
+    {
+      "printer-name",
+      "printer-uri-supported",
+      "member-uris"
+    };
   if (cups_backend->list_printers_pending ||
       !cups_backend->got_default_printer)
     return TRUE;
@@ -1125,6 +1096,10 @@ cups_request_printer_list (GtkPrintBackendCups *cups_backend)
                                  NULL,
                                  NULL);
 
+  gtk_cups_request_ipp_add_strings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+                                   "requested-attributes", G_N_ELEMENTS (pattrs),
+                                   NULL, pattrs);
+
   cups_request_execute (cups_backend,
                         request,
                         (GtkPrintCupsResponseCallbackFunc) cups_request_printer_list_cb,
@@ -1136,29 +1111,19 @@ cups_request_printer_list (GtkPrintBackendCups *cups_backend)
   return TRUE;
 }
 
-static GList * 
-cups_get_printer_list (GtkPrintBackend *print_backend)
+static void
+cups_get_printer_list (GtkPrintBackend *backend)
 {
   GtkPrintBackendCups *cups_backend;
-  GList *result;
-
-  cups_backend = GTK_PRINT_BACKEND_CUPS (print_backend);
-
-  result = NULL;
-  if (cups_backend->printers != NULL)
-    g_hash_table_foreach (cups_backend->printers,
-                          (GHFunc) printer_hash_to_sorted_active_list,
-                          &result);
 
+  cups_backend = GTK_PRINT_BACKEND_CUPS (backend);
   if (cups_backend->list_printers_poll == 0)
     {
       cups_request_printer_list (cups_backend);
-      cups_backend->list_printers_poll = g_timeout_add (3000,
+      cups_backend->list_printers_poll = g_timeout_add (3000 * 100000,
                                                         (GSourceFunc) cups_request_printer_list,
-                                                        print_backend);
+                                                        backend);
     }
-  return result;
 }
 
 typedef struct {
index c36b8077e548fb4e6b74c7a2629619193bf2fa54..89713339e717f1764217ffe94ccab34b7609e1f5 100644 (file)
@@ -90,8 +90,7 @@ gtk_printer_cups_finalize (GObject *object)
   if (printer->ppd_file)
     ppdClose (printer->ppd_file);
 
-  if (G_OBJECT_CLASS (gtk_printer_cups_parent_class)->finalize)
-    G_OBJECT_CLASS (gtk_printer_cups_parent_class)->finalize (object);
+  G_OBJECT_CLASS (gtk_printer_cups_parent_class)->finalize (object);
 }
 
 /**
index 4560c92a2f3e0a82d30ed1cf6bcf61e6ba150321..daed2e589b9c39c0f1c159fbe5456e92bd246b2a 100644 (file)
@@ -51,25 +51,18 @@ static GType print_backend_lpr_type = 0;
 
 struct _GtkPrintBackendLprClass
 {
-  GObjectClass parent_class;
+  GtkPrintBackendClass parent_class;
 };
 
 struct _GtkPrintBackendLpr
 {
-  GObject parent_instance;
-
-  GtkPrinter *printer;
-
-  GHashTable *printers;
+  GtkPrintBackend parent_instance;
 };
 
 static GObjectClass *backend_parent_class;
 
 static void                 gtk_print_backend_lpr_class_init      (GtkPrintBackendLprClass *class);
-static void                 gtk_print_backend_lpr_iface_init      (GtkPrintBackendIface    *iface);
 static void                 gtk_print_backend_lpr_init            (GtkPrintBackendLpr      *impl);
-static void                 gtk_print_backend_lpr_finalize        (GObject                 *object);
-static GList *              lpr_request_printer_list              (GtkPrintBackend         *print_backend);
 static void                 lpr_printer_get_settings_from_options (GtkPrinter              *printer,
                                                                   GtkPrinterOptionSet     *options,
                                                                   GtkPrintSettings        *settings);
@@ -89,6 +82,16 @@ static void                 lpr_printer_get_hard_margins          (GtkPrinter
                                                                   double                  *right);
 static void                 lpr_printer_request_details           (GtkPrinter              *printer);
 static GList *              lpr_printer_list_papers               (GtkPrinter              *printer);
+static cairo_surface_t *    lpr_printer_create_cairo_surface      (GtkPrinter              *printer,
+                                                                  gdouble                  width,
+                                                                  gdouble                  height,
+                                                                  gint                     cache_fd);
+static void                 gtk_print_backend_lpr_print_stream    (GtkPrintBackend         *print_backend,
+                                                                  GtkPrintJob             *job,
+                                                                  gint                     data_fd,
+                                                                  GtkPrintJobCompleteFunc  callback,
+                                                                  gpointer                 user_data,
+                                                                  GDestroyNotify           dnotify);
 
 static void
 gtk_print_backend_lpr_register_type (GTypeModule *module)
@@ -108,24 +111,11 @@ gtk_print_backend_lpr_register_type (GTypeModule *module)
        (GInstanceInitFunc) gtk_print_backend_lpr_init,
       };
 
-      static const GInterfaceInfo print_backend_info =
-      {
-       (GInterfaceInitFunc) gtk_print_backend_lpr_iface_init, /* interface_init */
-       NULL,                                                 /* interface_finalize */
-       NULL                                                  /* interface_data */
-      };
-
       print_backend_lpr_type = g_type_module_register_type (module,
-                                                             G_TYPE_OBJECT,
-                                                            "GtkPrintBackendLpr",
-                                                            &print_backend_lpr_info, 0);
-      g_type_module_add_interface (module,
-                                   print_backend_lpr_type,
-                                  GTK_TYPE_PRINT_BACKEND,
-                                  &print_backend_info);
+                                                           GTK_TYPE_PRINT_BACKEND,
+                                                           "GtkPrintBackendLpr",
+                                                           &print_backend_lpr_info, 0);
     }
-
-
 }
 
 G_MODULE_EXPORT void 
@@ -173,11 +163,19 @@ gtk_print_backend_lpr_new (void)
 static void
 gtk_print_backend_lpr_class_init (GtkPrintBackendLprClass *class)
 {
-  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
-
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_CLASS (class);
+  
   backend_parent_class = g_type_class_peek_parent (class);
 
-  gobject_class->finalize = gtk_print_backend_lpr_finalize;
+  backend_class->print_stream = gtk_print_backend_lpr_print_stream;
+  backend_class->printer_request_details = lpr_printer_request_details;
+  backend_class->printer_create_cairo_surface = lpr_printer_create_cairo_surface;
+  backend_class->printer_get_options = lpr_printer_get_options;
+  backend_class->printer_mark_conflicts = lpr_printer_mark_conflicts;
+  backend_class->printer_get_settings_from_options = lpr_printer_get_settings_from_options;
+  backend_class->printer_prepare_for_print = lpr_printer_prepare_for_print;
+  backend_class->printer_list_papers = lpr_printer_list_papers;
+  backend_class->printer_get_hard_margins = lpr_printer_get_hard_margins;
 }
 
 static cairo_status_t
@@ -215,22 +213,6 @@ lpr_printer_create_cairo_surface (GtkPrinter *printer,
   return surface;
 }
 
-static GtkPrinter *
-gtk_print_backend_lpr_find_printer (GtkPrintBackend *print_backend,
-                                     const gchar *printer_name)
-{
-  GtkPrintBackendLpr *lpr_print_backend;
-  GtkPrinter *printer;
-
-  lpr_print_backend = GTK_PRINT_BACKEND_LPR (print_backend);
-  
-  printer = NULL;
-  if (strcmp (gtk_printer_get_name (lpr_print_backend->printer), printer_name) == 0)
-    printer = lpr_print_backend->printer;
-
-  return printer; 
-}
-
 typedef struct {
   GtkPrintBackend *backend;
   GtkPrintJobCompleteFunc callback;
@@ -398,64 +380,21 @@ gtk_print_backend_lpr_print_stream (GtkPrintBackend *print_backend,
   g_strfreev (argv);
 }
 
-
 static void
-gtk_print_backend_lpr_iface_init (GtkPrintBackendIface *iface)
-{
-  iface->get_printer_list = lpr_request_printer_list;
-  iface->find_printer = gtk_print_backend_lpr_find_printer;
-  iface->print_stream = gtk_print_backend_lpr_print_stream;
-  iface->printer_request_details = lpr_printer_request_details;
-  iface->printer_create_cairo_surface = lpr_printer_create_cairo_surface;
-  iface->printer_get_options = lpr_printer_get_options;
-  iface->printer_mark_conflicts = lpr_printer_mark_conflicts;
-  iface->printer_get_settings_from_options = lpr_printer_get_settings_from_options;
-  iface->printer_prepare_for_print = lpr_printer_prepare_for_print;
-  iface->printer_list_papers = lpr_printer_list_papers;
-  iface->printer_get_hard_margins = lpr_printer_get_hard_margins;
-}
-
-static GList *
-lpr_request_printer_list (GtkPrintBackend *backend)
-{
-  GList *l;
-  GtkPrintBackendLpr *lpr_backend;
-
-  l = NULL;
-
-  lpr_backend = GTK_PRINT_BACKEND_LPR (backend);
-  
-  if (lpr_backend->printer)
-    l = g_list_append (l, lpr_backend->printer);
-
-  return l; 
-}
-
-static void
-gtk_print_backend_lpr_init (GtkPrintBackendLpr *backend_lpr)
+gtk_print_backend_lpr_init (GtkPrintBackendLpr *backend)
 {
   GtkPrinter *printer;
 
   printer = gtk_printer_new (_("Print to LPR"),
-                            GTK_PRINT_BACKEND (backend_lpr),
+                            GTK_PRINT_BACKEND (backend),
                             TRUE); 
   gtk_printer_set_has_details (printer, TRUE);
   gtk_printer_set_icon_name (printer, "printer");
   gtk_printer_set_is_active (printer, TRUE);
-  
-  backend_lpr->printer = printer;
-}
-
-static void
-gtk_print_backend_lpr_finalize (GObject *object)
-{
-  GtkPrintBackendLpr *backend_lpr;
-
-  backend_lpr = GTK_PRINT_BACKEND_LPR (object);
-
-  g_object_unref (backend_lpr->printer);
+  gtk_printer_set_is_default (printer, TRUE);
 
-  backend_parent_class->finalize (object);
+  gtk_print_backend_add_printer (GTK_PRINT_BACKEND (backend), printer);
+  g_object_unref (printer);
 }
 
 static void
index e746f92d46b4e38723a45b284858366e7979caee..206b2c1a8e8026470b3774b316fdbcd09fe25b27 100644 (file)
@@ -52,25 +52,18 @@ static GType print_backend_pdf_type = 0;
 
 struct _GtkPrintBackendPdfClass
 {
-  GObjectClass parent_class;
+  GtkPrintBackendClass parent_class;
 };
 
 struct _GtkPrintBackendPdf
 {
-  GObject parent_instance;
-
-  GtkPrinter *printer;
-
-  GHashTable *printers;
+  GtkPrintBackend parent_instance;
 };
 
 static GObjectClass *backend_parent_class;
 
 static void                 gtk_print_backend_pdf_class_init      (GtkPrintBackendPdfClass *class);
-static void                 gtk_print_backend_pdf_iface_init      (GtkPrintBackendIface    *iface);
 static void                 gtk_print_backend_pdf_init            (GtkPrintBackendPdf      *impl);
-static void                 gtk_print_backend_pdf_finalize        (GObject                 *object);
-static GList *              pdf_request_printer_list              (GtkPrintBackend         *print_backend);
 static void                 pdf_printer_get_settings_from_options (GtkPrinter              *printer,
                                                                   GtkPrinterOptionSet     *options,
                                                                   GtkPrintSettings        *settings);
@@ -90,6 +83,16 @@ static void                 pdf_printer_get_hard_margins          (GtkPrinter
                                                                   double                  *right);
 static void                 pdf_printer_request_details           (GtkPrinter              *printer);
 static GList *              pdf_printer_list_papers               (GtkPrinter              *printer);
+static void                 gtk_print_backend_pdf_print_stream    (GtkPrintBackend         *print_backend,
+                                                                  GtkPrintJob             *job,
+                                                                  gint                     data_fd,
+                                                                  GtkPrintJobCompleteFunc  callback,
+                                                                  gpointer                 user_data,
+                                                                  GDestroyNotify           dnotify);
+static cairo_surface_t *    pdf_printer_create_cairo_surface      (GtkPrinter              *printer,
+                                                                  gdouble                  width,
+                                                                  gdouble                  height,
+                                                                  gint                     cache_fd);
 
 static void
 gtk_print_backend_pdf_register_type (GTypeModule *module)
@@ -109,24 +112,11 @@ gtk_print_backend_pdf_register_type (GTypeModule *module)
        (GInstanceInitFunc) gtk_print_backend_pdf_init,
       };
 
-      static const GInterfaceInfo print_backend_info =
-      {
-       (GInterfaceInitFunc) gtk_print_backend_pdf_iface_init, /* interface_init */
-       NULL,                                                 /* interface_finalize */
-       NULL                                                  /* interface_data */
-      };
-
       print_backend_pdf_type = g_type_module_register_type (module,
-                                                             G_TYPE_OBJECT,
-                                                            "GtkPrintBackendPdf",
-                                                            &print_backend_pdf_info, 0);
-      g_type_module_add_interface (module,
-                                   print_backend_pdf_type,
-                                  GTK_TYPE_PRINT_BACKEND,
-                                  &print_backend_info);
+                                                           GTK_TYPE_PRINT_BACKEND,
+                                                           "GtkPrintBackendPdf",
+                                                           &print_backend_pdf_info, 0);
     }
-
-
 }
 
 G_MODULE_EXPORT void 
@@ -174,11 +164,19 @@ gtk_print_backend_pdf_new (void)
 static void
 gtk_print_backend_pdf_class_init (GtkPrintBackendPdfClass *class)
 {
-  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_CLASS (class);
 
   backend_parent_class = g_type_class_peek_parent (class);
 
-  gobject_class->finalize = gtk_print_backend_pdf_finalize;
+  backend_class->print_stream = gtk_print_backend_pdf_print_stream;
+  backend_class->printer_request_details = pdf_printer_request_details;
+  backend_class->printer_create_cairo_surface = pdf_printer_create_cairo_surface;
+  backend_class->printer_get_options = pdf_printer_get_options;
+  backend_class->printer_mark_conflicts = pdf_printer_mark_conflicts;
+  backend_class->printer_get_settings_from_options = pdf_printer_get_settings_from_options;
+  backend_class->printer_prepare_for_print = pdf_printer_prepare_for_print;
+  backend_class->printer_list_papers = pdf_printer_list_papers;
+  backend_class->printer_get_hard_margins = pdf_printer_get_hard_margins;
 }
 
 static cairo_status_t
@@ -216,22 +214,6 @@ pdf_printer_create_cairo_surface (GtkPrinter *printer,
   return surface;
 }
 
-static GtkPrinter *
-gtk_print_backend_pdf_find_printer (GtkPrintBackend *print_backend,
-                                     const gchar *printer_name)
-{
-  GtkPrintBackendPdf *pdf_print_backend;
-  GtkPrinter *printer;
-
-  pdf_print_backend = GTK_PRINT_BACKEND_PDF (print_backend);
-  
-  printer = NULL;
-  if (strcmp (gtk_printer_get_name (pdf_print_backend->printer), printer_name) == 0)
-    printer = pdf_print_backend->printer;
-
-  return printer; 
-}
-
 typedef struct {
   GtkPrintBackend *backend;
   GtkPrintJobCompleteFunc callback;
@@ -366,64 +348,23 @@ gtk_print_backend_pdf_print_stream (GtkPrintBackend *print_backend,
                   ps);
 }
 
-
 static void
-gtk_print_backend_pdf_iface_init (GtkPrintBackendIface *iface)
-{
-  iface->get_printer_list = pdf_request_printer_list;
-  iface->find_printer = gtk_print_backend_pdf_find_printer;
-  iface->print_stream = gtk_print_backend_pdf_print_stream;
-  iface->printer_request_details = pdf_printer_request_details;
-  iface->printer_create_cairo_surface = pdf_printer_create_cairo_surface;
-  iface->printer_get_options = pdf_printer_get_options;
-  iface->printer_mark_conflicts = pdf_printer_mark_conflicts;
-  iface->printer_get_settings_from_options = pdf_printer_get_settings_from_options;
-  iface->printer_prepare_for_print = pdf_printer_prepare_for_print;
-  iface->printer_list_papers = pdf_printer_list_papers;
-  iface->printer_get_hard_margins = pdf_printer_get_hard_margins;
-}
-
-static GList *
-pdf_request_printer_list (GtkPrintBackend *backend)
-{
-  GList *l;
-  GtkPrintBackendPdf *pdf_backend;
-
-  l = NULL;
-
-  pdf_backend = GTK_PRINT_BACKEND_PDF (backend);
-  
-  if (pdf_backend->printer)
-    l = g_list_append (l, pdf_backend->printer);
-
-  return l; 
-}
-
-static void
-gtk_print_backend_pdf_init (GtkPrintBackendPdf *backend_pdf)
+gtk_print_backend_pdf_init (GtkPrintBackendPdf *backend)
 {
   GtkPrinter *printer;
   
-  backend_pdf->printer = gtk_printer_new (_("Print to PDF"),
-                                         GTK_PRINT_BACKEND (backend_pdf),
-                                         TRUE); 
+  printer = gtk_printer_new (_("Print to PDF"),
+                            GTK_PRINT_BACKEND (backend),
+                            TRUE); 
 
-  printer = backend_pdf->printer;
   gtk_printer_set_has_details (printer, TRUE);
   gtk_printer_set_icon_name (printer, "floppy");
   gtk_printer_set_is_active (printer, TRUE);
-}
-
-static void
-gtk_print_backend_pdf_finalize (GObject *object)
-{
-  GtkPrintBackendPdf *backend_pdf;
-
-  backend_pdf = GTK_PRINT_BACKEND_PDF (object);
 
-  g_object_unref (backend_pdf->printer);
+  gtk_print_backend_add_printer (GTK_PRINT_BACKEND (backend), printer);
+  g_object_unref (printer);
 
-  backend_parent_class->finalize (object);
+  gtk_print_backend_set_list_done (GTK_PRINT_BACKEND (backend));
 }
 
 static void
index a900f8d5fbbed9ae910ce25d71e69723371bd685..c5d269ec42f4c4c211224a5f373dd59ffca1cb3c 100644 (file)
@@ -53,6 +53,7 @@ noinst_PROGRAMS =                     \
        testmultidisplay                \
        testmultiscreen                 \
        testnotebookdnd                 \
+       testnouiprint                   \
        testrgb                         \
        testrecentchooser               \
        testselection                   \
@@ -107,6 +108,7 @@ testmenubars_DEPENDENCIES = $(TEST_DEPS)
 testmultidisplay_DEPENDENCIES = $(TEST_DEPS)
 testmultiscreen_DEPENDENCIES = $(TEST_DEPS)
 testnotebookdnd_DEPENDENCIES = $(TEST_DEPS)
+testnouiprint_DEPENDENCIES = $(TEST_DEPS)
 testrecentchooser_DEPENDENCIES = $(TEST_DEPS)
 testrgb_DEPENDENCIES = $(TEST_DEPS)
 testselection_DEPENDENCIES = $(TEST_DEPS)
@@ -155,6 +157,7 @@ testmenubars_LDADD = $(LDADDS)
 testmultidisplay_LDADD = $(LDADDS)
 testmultiscreen_LDADD = $(LDADDS)
 testnotebookdnd_LDADD = $(LDADDS)
+testnouiprint_LDADD = $(LDADDS)
 testrecentchooser_LDADD = $(LDADDS)
 testrgb_LDADD = $(LDADDS)
 testselection_LDADD = $(LDADDS)
diff --git a/tests/testnouiprint.c b/tests/testnouiprint.c
new file mode 100644 (file)
index 0000000..3b0825b
--- /dev/null
@@ -0,0 +1,107 @@
+/* -*- Mode: C; c-basic-offset: 2; -*- */
+/* Gtk+ - non-ui printing
+ *
+ * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "gtk/gtkprintoperation.h"
+#include <math.h>
+
+static void
+draw_page (GtkPrintOperation *operation,
+          GtkPrintContext *context,
+          int page_nr)
+{
+  cairo_t *cr;
+  PangoLayout *layout;
+  PangoFontDescription *desc;
+  
+  cr = gtk_print_context_get_cairo (context);
+
+  /* Draw a red rectangle, as wide as the paper (inside the margins) */
+  cairo_set_source_rgb (cr, 1.0, 0, 0);
+  cairo_rectangle (cr, 0, 0, gtk_print_context_get_width (context), 50);
+  
+  cairo_fill (cr);
+
+  /* Draw some lines */
+  cairo_move_to (cr, 20, 10);
+  cairo_line_to (cr, 40, 20);
+  cairo_arc (cr, 60, 60, 20, 0, M_PI);
+  cairo_line_to (cr, 80, 20);
+  
+  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_set_line_width (cr, 5);
+  cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+  cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+  
+  cairo_stroke (cr);
+
+  /* Draw some text */
+  
+  layout = gtk_print_context_create_layout (context);
+  pango_layout_set_text (layout, "Hello World! Printing is easy", -1);
+  desc = pango_font_description_from_string ("sans 28");
+  pango_layout_set_font_description (layout, desc);
+  pango_font_description_free (desc);
+
+  cairo_move_to (cr, 30, 20);
+  pango_cairo_layout_path (cr, layout);
+
+  /* Font Outline */
+  cairo_set_source_rgb (cr, 0.93, 1.0, 0.47);
+  cairo_set_line_width (cr, 0.5);
+  cairo_stroke_preserve (cr);
+
+  /* Font Fill */
+  cairo_set_source_rgb (cr, 0, 0.0, 1.0);
+  cairo_fill (cr);
+  
+  g_object_unref (layout);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  GMainLoop *loop;
+  GtkPrintOperation *print;
+  GtkPrintOperationResult res;
+  GtkPrintSettings *settings;
+
+  
+  /* Unfortunately we need a display for the XSettings to get the
+     list of backends... */
+  /* gtk_parse_args (&argc, &argv); */
+  gtk_init (&argc, &argv);
+
+  loop = g_main_loop_new (NULL, TRUE);
+
+  settings = gtk_print_settings_new ();
+  /* gtk_print_settings_set_printer (settings, "printer"); */
+  
+  print = gtk_print_operation_new ();
+  gtk_print_operation_set_print_settings (print, settings);
+  gtk_print_operation_set_nr_of_pages (print, 1);
+  gtk_print_operation_set_unit (print, GTK_UNIT_MM);
+  gtk_print_operation_set_show_dialog (print, FALSE);
+  g_signal_connect (print, "draw_page", G_CALLBACK (draw_page), NULL);
+  res = gtk_print_operation_run (print, NULL, NULL);
+
+  return 0;
+}